#include "cepollservermgr.h"
#include "cepollserverthread.h"
#include "cepollworkthread.h"

#include "cpublicdata.h"
#include "cclientdata.h"
#include "clogoper.h"
#include "cglobal.h"

CEpollServerMgr::CEpollServerMgr(QObject* parent) : QObject(parent)
{
    m_pLog = &CLogOper::instance();
    m_pServerThread = new CEpollServerThread;

    init();
}

CEpollServerMgr::~CEpollServerMgr()
{
    stopServer();
}

bool CEpollServerMgr::startServer(int nPort)
{
    if (true == m_pServerThread->isRunning())
    {
        emit slotHandleServerLogMsg(enWorkInfo, A2T("TCP服务端"), A2T("服务端已启动"));
        return false;
    }
    if (true == m_pServerThread->startServer(nPort))
    {
        emit sigServerStatusChanged(enServerRunning);
        QList<CClientData*> listClient = CPublicData::instance().m_listClient;
        for (int i = 0; i < listClient.size(); i++)
        {
            connect(this, &CEpollServerMgr::sigClientStatusChanged, listClient.at(i)
                    , &CClientData::slotClientStatusChanged, Qt::QueuedConnection);
        }
        return true;
    }
    else
    {
        return false;
    }
}

void CEpollServerMgr::stopServer()
{
    m_pServerThread->stopServer();
    m_threadPool.clear();

    QMutexLocker locker(&m_mutex);
    QMap<int, SClientCfg>::iterator itor;
    for (itor = m_mapClient.begin(); itor != m_mapClient.end(); itor++)
    {
        close(itor.key());
    }
    m_mapClient.clear();
    QList<CClientData*> listClient = CPublicData::instance().m_listClient;
    for (int i = 0; i < listClient.size(); i++)
    {
        disconnect(this, &CEpollServerMgr::sigClientStatusChanged
                , listClient.at(i), &CClientData::slotClientStatusChanged);
    }

    emit sigServerStatusChanged(enServerStopped);
}

void CEpollServerMgr::setThreadPoolSize(int nSize)
{
    m_threadPool.setMaxThreadCount(nSize);
}

void CEpollServerMgr::init()
{
    connect(m_pServerThread, &CEpollServerThread::sigNewConnection, this, &CEpollServerMgr::slotHandleNewConnection);
    connect(m_pServerThread, &CEpollServerThread::sigReadReady, this, &CEpollServerMgr::slotHandleReadReady);
    connect(m_pServerThread, &CEpollServerThread::sigConnectionClosed, this, &CEpollServerMgr::slotHandleConnectionClosed);
    connect(m_pServerThread, &CEpollServerThread::sigLogMsg, this, &CEpollServerMgr::slotHandleServerLogMsg);
}

void CEpollServerMgr::slotHandleNewConnection(int nClientFd, sockaddr_in* pClientAddr)
{
    QMutexLocker locker(&m_mutex);

    SClientCfg stClientCfg(nClientFd, ntohs(pClientAddr->sin_port), ntohl(pClientAddr->sin_addr.s_addr));
    CClientData* pClient = CPublicData::instance().m_mapClient.value(stClientCfg.m_addr.toString());
    stClientCfg.m_sName = pClient->m_sName;
    m_mapClient.insert(nClientFd, stClientCfg);
    emit sigClientStatusChanged(stClientCfg.m_sGuid, true);

    slotHandleServerLogMsg(enWorkInfo, A2T("TCP服务端"), A2T("新连接 %1 已建立,名称 %2")
                     .arg(stClientCfg.m_sGuid).arg(stClientCfg.m_sName));
}

void CEpollServerMgr::slotHandleReadReady(int nFd)
{
    CEpollWorkThread* pWorkThread = new CEpollWorkThread(nFd);
    pWorkThread->setAutoDelete(true);
    SClientCfg stClientCfg = m_mapClient.value(nFd);
    pWorkThread->setClientConfig(stClientCfg);
    CClientData* pClientData = CPublicData::instance().m_mapClient.value(stClientCfg.m_addr.toString());
    pWorkThread->setClientData(pClientData);
    m_threadPool.start(pWorkThread);
    if (false == pWorkThread->m_bConnected)
    {
        connect(pWorkThread, &CEpollWorkThread::sigRunningLogMsg, this, &CEpollServerMgr::slotHandleWorkLogMsg);
        connect(pWorkThread, &CEpollWorkThread::sigConnectionClosed, this, &CEpollServerMgr::slotHandleConnectionClosed);
        pWorkThread->m_bConnected = true;
    }
}

void CEpollServerMgr::slotHandleConnectionClosed(int nFd)
{
    QMutexLocker locker(&m_mutex);
    close(nFd);
    if (false == m_mapClient.contains(nFd)) return;
    SClientCfg stClientCfg = m_mapClient.value(nFd);
    m_mapClient.remove(nFd);
    slotHandleServerLogMsg(enWorkInfo, A2T("TCP服务端"), A2T("客户端 %1 连接已关闭,名称 %2")
                         .arg(stClientCfg.m_sGuid).arg(stClientCfg.m_sName));
    emit sigClientStatusChanged(stClientCfg.m_sGuid, false);
}

void CEpollServerMgr::slotHandleServerLogMsg(const int &nLevel, const QString &sMod, const QString &sMsg)
{
    SExecLog stLog;
    stLog.m_nAlarmLevel = nLevel;
    stLog.m_sDevName = sMod;
    stLog.m_sDescription = sMsg;
    if (m_pLog) m_pLog->addMsg("", stLog);
}

void CEpollServerMgr::slotHandleWorkLogMsg(const int& nFd, const int& nLevel, const QString& sMod, const QString& sMsg)
{
    SExecLog stLog;
    stLog.m_nAlarmLevel = nLevel;
    stLog.m_sDevName = sMod;
    stLog.m_sDescription = sMsg;
    QString sGuid = m_mapClient.value(nFd).m_sGuid;

    if (m_pLog) m_pLog->addMsg(sGuid, stLog);
}
